﻿using SelfManagement.Database;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Linq.Expressions;
using System.Data.Entity;
using SelfManagement.Database.Common;
using SelfManagement.Utility.Extensions;
using Ninject;

namespace SelfManagement.Database.EF
{
    public class BaseRepository<T> : IBaseRepository<T> where T : EntityBase, new()
    {
        [Inject]
        public SelfManagementContext SelfManagementDB { get; set; }

        /// <summary>
        /// 删除对象
        /// </summary>
        public virtual bool Delete(T obj, bool saveChange = true)
        {
            var tbl = SelfManagementDB.Set<T>();
            if (!tbl.Local.Contains(obj))
            {
                SelfManagementDB.Entry(obj).State = EntityState.Deleted;
            }
            else
            {
                SelfManagementDB.Set<T>().Remove(obj);
            }

            return !saveChange || SelfManagementDB.SaveChanges() > 0;
        }

        /// <summary>
        /// 批量删除对象
        /// </summary>
        public virtual bool DeleteBatch(Expression<Func<T, bool>> predicate, bool saveChange = true)
        {
            var tbl = SelfManagementDB.Set<T>();
            IQueryable<T> query = tbl;
            if (predicate != null)
                query = query.Where(predicate);
            var objs = query.AsEnumerable();

            foreach (var entity in objs)
                tbl.Remove(entity);

            return !saveChange || SelfManagementDB.SaveChanges() > 0;
        }

        /// <summary>
        /// 获取单条数据
        /// </summary>
        public virtual T Get(Expression<Func<T, bool>> predicate)
        {
            IQueryable<T> query = SelfManagementDB.Set<T>();
            if (predicate != null)
                query = query.Where(predicate);
            return query.FirstOrDefault();
        }

        /// <summary>
        /// 新增记录
        /// </summary>
        public virtual bool Insert(T obj, bool saveChange = true)
        {
            try
            {
                SetEntityCommonProperty(obj, true);

                var tbl = SelfManagementDB.Set<T>();
                obj = tbl.Add(obj);
                return !saveChange || SelfManagementDB.SaveChanges() > 0;
            }
            catch (System.Data.Entity.Validation.DbEntityValidationException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 批量更新
        /// </summary>
        public virtual bool InsertBatch(IEnumerable<T> objs, bool saveChange = true)
        {
            objs.ForEach(o => SetEntityCommonProperty(o, true));

            var tbl = SelfManagementDB.Set<T>();
            foreach (var obj in objs)
            {
                tbl.Add(obj);
            }
            return !saveChange || SelfManagementDB.SaveChanges() > 0;
        }

        public virtual T New()
        {
            var obj = new T();
            obj.Id = Guid.NewGuid().ToString();
            return obj;
        }

        /// <summary>
        /// 查询
        /// </summary>
        public virtual IQueryable<T> Query(Expression<Func<T, bool>> predicate = null)
        {
            IQueryable<T> query = SelfManagementDB.Set<T>();
            if (predicate != null)
                query = query.Where(predicate);

            return query;
        }

        /// <summary>
        /// 更新
        /// </summary>
        public virtual bool Update(T obj, Func<T, object[]> getKeys = null, bool saveChange = true, bool updateTime = true)
        {
            if (getKeys.IsNull())
            {
                getKeys = o => new object[] { o.Id };
            }

            SetEntityCommonProperty(obj, false, updateTime);

            var entry = SelfManagementDB.Entry(obj);

            if (entry.State == EntityState.Detached)
            {
                var tbl = SelfManagementDB.Set<T>();
                var keys = getKeys(obj);
                var currentEntry = tbl.Find(keys);
                if (currentEntry != null)
                {
                    var attachedEntry = SelfManagementDB.Entry(currentEntry);
                    attachedEntry.CurrentValues.SetValues(obj);
                    attachedEntry.State = EntityState.Modified;
                }
                else
                {
                    tbl.Attach(obj);
                    entry.State = EntityState.Modified;
                }
            }

            return !saveChange || SelfManagementDB.SaveChanges() > 0;
        }

        /// <summary>
        /// 批量更新
        /// </summary>
        public virtual bool UpdateBatch(Expression<Func<T, bool>> predicate, Func<T, T> setter, bool saveChange = true)
        {
            IQueryable<T> query = SelfManagementDB.Set<T>();
            if (predicate != null)
                query = query.Where(predicate);
            //var objs = query.AsEnumerable();

            //var func = setter.Compile();

            foreach (var obj in query)
            {
                setter(obj);
                SetEntityCommonProperty(obj, false);
            }

            //try
            //{
            return !saveChange || SelfManagementDB.SaveChanges() > 0;
            //}
            //catch(System.Data.Entity.Validation.DbEntityValidationException ex)
            //{
            //    return false;
            //}
        }

        public virtual void Dispose()
        {
            //if (db == null)
            //    return;
            //db.Dispose();
            //db = null;
            //GC.SuppressFinalize(this);
        }

        private void SetEntityCommonProperty(T entity, bool isCreating, bool updateTime = true)
        {
            if (isCreating)
            {
                if(entity.Id.IsNull())
                    entity.Id = Guid.NewGuid().ToString();
                entity.CreatedTime = DateTime.Now;
                if (entity.CreatedBy.IsNullOrWhiteSpace())
                {
                    entity.CreatedBy = "系统";
                }
            }
            if (updateTime)
            {
                entity.UpdatedTime = DateTime.Now;
            }
            if (entity.UpdatedBy.IsNullOrWhiteSpace())
            {
                entity.UpdatedBy = "系统";
            }
        }

        /// <summary>
        /// 保存所有修改
        /// </summary>
        public bool SaveChanges()
        {
            return SelfManagementDB.SaveChanges() > 0;
        }
    }
}
